/**
 * NPC角色的基类，继承自APawnBaseCpp类。
 * 向上包括了基类公共的方法和属性。
 * 向下包括了不同NPC的公共方法和属性.
 * 任何继承自该类的NPC派生类都应在代码中自行实现以下方法：
 * SetNPCDead
 * DeadTimerCallback
 */
#pragma once

#include "CoreMinimal.h"
#include "HeaderDataCpp.h"
#include "PawnBaseCpp.h"
#include "Kismet/GameplayStatics.h"
#include "Components/BoxComponent.h"
#include "NPCBaseCpp.generated.h"

UENUM(Blueprintable)
enum class ENPCAction : uint8 { E_Idle, E_Run, E_Walk, E_Attack, E_Dead, E_Attack1, E_Attack2, E_Attack3 };

UENUM(Blueprintable)
enum class ENPCAnim : uint8 { E_IdleLeft, E_IdleRight, E_WalkLeft, E_WalkRight, E_RunLeft, E_RunRight,
	E_AttackLeft, E_AttackRight, E_DeadLeft, E_DeadRight, E_Attack1, E_Attack2, E_Attack3 };

class ANPCAreaBaseCpp;

/**
 * 
 */
UCLASS()
class ACTIONGAME_API ANPCBaseCpp : public APawnBaseCpp
{
	GENERATED_BODY()
public:
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	float WalkSpeed;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	float RunSpeed;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	float SafeDistance;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	ENPCAction ActionState;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	ENPCAnim AnimState;

protected:
	FString NPCId;
	FVector LeftSide;
	FVector RightSide;
	FVector SpawnLocation;
	FVector SpawnDirection;
	bool locked;

	bool AbilityBusy;

	FVector MoveDirection;

	UPROPERTY()
	ANPCAreaBaseCpp* ParentArea;

	UPROPERTY()
	FTimerHandle DeadTimerHandle;

	UPROPERTY()
	FTimerHandle AttackTimerHandle;

	UPROPERTY()
	FTimerHandle DamageTimerHandle;

	UPROPERTY()
	int DropItemAmount;

	UPROPERTY()
	EItemType DropItemType;

	UPROPERTY()
	float BaseDamage;

	UPROPERTY()
	float ProDamage;
	
public:
	ANPCBaseCpp();

	/**
	 * 对一个NPC自身造成伤害，影响HP值，覆盖系统方法。
	 */
	virtual float TakeDamage(float DamageAmount, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser) override;
public:

	UFUNCTION(BlueprintCallable)
    void SetSpawnInfo(const FString Id, const float HPConfig, const FVector LeftSideConfig, const FVector RightSideConfig, const FVector SpawnLocationConfig, const FVector SpawnDirectionConfig, ANPCAreaBaseCpp* Parent, const int DropAmountConfig, const EItemType DropTypeConfig);
	
	/**
	 * 正常行走的方法，行走速度有随机数得到，碰到左右边界就修改MoveDirection并反向运动。
	 */
	virtual void Walk(const float DeltaTime);

	/**
	 * 追击玩家的方法。与玩家角色保持SafeDistance的距离，追击时和同类也会保持SafeDistance的距离。
	 * @param DeltaTime
	 * @param TargetLocation 玩家角色的位置。
	 */
	virtual bool Run(const float DeltaTime, const FVector TargetLocation);

	/**
	 * 攻击方法，派生类的NPC可覆盖该方法。该方法启动两个定时器
	 */
	virtual void Attack(const float AttackAnimTime, const float DamageTriggerTime);

	/**
	 * 攻击方法计时器的回调函数
	 */
	virtual void AttackTimerCallback();

	/**
	 * 对玩家造成伤害的计时器的回调函数
	 */
	virtual void DamageTimerCallback();
	
	/**
	 * 返回左边界坐标。
	 * @return LeftSide FVector
	 */
	FVector GetLeftSide() const;

	/**
	* 返回右边界坐标。
	* @return RightSide FVector
	*/
	FVector GetRightSide() const;

	/**
	 * 通知所属NPCArea设置NPC存活状态字典，并更新动画状态。在子类的覆盖的DeadTimerCallback方法中调用。
	 */
	virtual void SetDead();

	/**
	 * 播放死亡动画的计时器，在这里对所属NPCArea调用SetDead方法。
	 */
	virtual void DeadTimerCallback();

	/**
	 * 根据目标动画状态设置动画资源文件。在子类蓝图中实现。
	 */
	UFUNCTION(BlueprintImplementableEvent)
	void UpdateAnimStateMachine(const ENPCAnim TargetAnimState);

	/**
	 * 当所属NPCArea有玩家角色进入时，由所属NPCArea对存活状态字典中的NPC调用该函数，以改变其动画状态。
	 */
	virtual void NotifyNPCOnChangingActionState(const ENPCAction TargetAction);

	/**
	 * 返回NPC的唯一ID
	 * @return NPCId FString，NPC的唯一ID
	 */
	inline FString GetNPCId() const;
	
protected:
	/**
	* 动画状态机，派生类可直接使用。
	*/
	inline ENPCAnim GetAnimStateByAction(ENPCAction& CurrentAction, ENPCAction TargetAction);
};
